﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ProjectEulerSolutions
{
    struct Fraction
    {
        public long Numerator;
        public long Denominator;

        public double Value
        {
            get
            {
                return Numerator / (double)Denominator;
            }
        }
        public double Wholes
        {
            get
            {
                return Numerator / Denominator;
            }
        }

        public Fraction(long numerator, long denominator)
        {
            int numSign = numerator < 0 ? -1 : 1;
            int denomSign = denominator < 0 ? -1 : 1;

            numerator *= numSign;
            denominator *= denomSign;
            numSign *= denomSign;

            long gcd = CommonFunctions.GreatestCommonDivisor(numerator, denominator);
            if (gcd > 1)
            {
                Numerator = numSign * (numerator / gcd);
                Denominator = denominator / gcd;
            }
            else
            {
                Numerator = numSign * numerator;
                Denominator = denominator;
            }
        }

        public static Fraction Inverse(Fraction fraction)
        {
            return new Fraction(fraction.Denominator, fraction.Numerator);
        }

        public static void Multiply(Fraction fraction1, Fraction fraction2, out Fraction result)
        {
            int f1Sign = fraction1.Numerator < 0 ? -1 : 1;
            int f2Sign = fraction2.Numerator < 0 ? -1 : 1;

            fraction1.Numerator *= f1Sign;
            fraction2.Numerator *= f2Sign;
            f1Sign *= f2Sign;

            long gcd1 = CommonFunctions.GreatestCommonDivisor(fraction1.Numerator, fraction2.Denominator);
            if (gcd1 > 1)
            {
                result.Numerator = fraction1.Numerator / gcd1;
                result.Denominator = fraction2.Denominator / gcd1;
            }
            else
            {
                result.Numerator = fraction1.Numerator;
                result.Denominator = fraction2.Denominator;
            }

            long gcd2 = CommonFunctions.GreatestCommonDivisor(fraction2.Numerator, fraction1.Denominator);

            if (gcd2 > 1)
            {
                result.Numerator *= fraction2.Numerator / gcd2;
                result.Denominator *= fraction1.Denominator / gcd2;
            }
            else
            {
                result.Numerator *= fraction2.Numerator;
                result.Denominator *= fraction1.Denominator;
            }

            result.Numerator *= f1Sign;
        }

        public static void Divide(Fraction fraction1, Fraction fraction2, out Fraction result)
        {
            int f1Sign = fraction1.Numerator < 0 ? -1 : 1;
            int f2Sign = fraction2.Numerator < 0 ? -1 : 1;

            fraction1.Numerator *= f1Sign;
            fraction2.Numerator *= f2Sign;
            f1Sign *= f2Sign;

            long gcd1 = CommonFunctions.GreatestCommonDivisor(fraction1.Numerator, fraction2.Numerator);
            if (gcd1 > 1)
            {
                result.Numerator = fraction1.Numerator / gcd1;
                result.Denominator = fraction2.Numerator / gcd1;
            }
            else
            {
                result.Numerator = fraction1.Numerator;
                result.Denominator = fraction2.Numerator;
            }

            long gcd2 = CommonFunctions.GreatestCommonDivisor(fraction2.Denominator, fraction1.Denominator);

            if (gcd2 > 1)
            {
                result.Numerator *= fraction2.Denominator / gcd2;
                result.Denominator *= fraction1.Denominator / gcd2;
            }
            else
            {
                result.Numerator *= fraction2.Denominator;
                result.Denominator *= fraction1.Denominator;
            }

            result.Numerator *= f1Sign;
        }

        public static void Add(Fraction fraction1, Fraction fraction2, out Fraction result)
        {
            long gcd = CommonFunctions.GreatestCommonDivisor(fraction1.Denominator, fraction2.Denominator);
            long commonDenominator = (fraction1.Denominator / gcd) * fraction2.Denominator;

            long numerator1 = fraction1.Numerator * (commonDenominator / fraction1.Denominator);
            long numerator2 = fraction2.Numerator * (commonDenominator / fraction2.Denominator);
            long numerator = numerator1 + numerator2;

            result = new Fraction(numerator, commonDenominator);
        }

        public static void Subtract(Fraction fraction1, Fraction fraction2, out Fraction result)
        {
            long gcd = CommonFunctions.GreatestCommonDivisor(fraction1.Denominator, fraction2.Denominator);
            long commonDenominator = (fraction1.Denominator / gcd) * fraction2.Denominator;

            long numerator1 = fraction1.Numerator * (commonDenominator / fraction1.Denominator);
            long numerator2 = fraction2.Numerator * (commonDenominator / fraction2.Denominator);
            long numerator = numerator1 - numerator2;

            result = new Fraction(numerator, commonDenominator);
        }

        public override string ToString()
        {
            return Numerator + "/" + Denominator;
        }
    }
}
